#!/usr/bin/python
#Developed by Florin Nicusor Coada for 216 CR
#Based on the udp_chat_server2.py tutorial from professor Christopher Peters
import socket


HOST = '192.168.1.2'  #Defaults to "this machine"
IPORT = 50007  #In            
OPORT = 50008  #Out

in_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
in_socket.bind((HOST, IPORT))

out_socket= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#Who's who
#address to name dict
users={}

##send message to all users
def sendAll(data):
    print "sending", data,"to",
    for i in users:
        out_socket.sendto(data,(i,OPORT))
        print i

##kick user
def kick(user,address):
    global users
    temp={}
    ##reacreate a list of users without the user that is going to be kicked
    for i in users:
        if users[i]!=user:
            temp[i]=users[i]
        else:
            ##if the user is online, send a message telling him that
            ##he has been kicked
            out_socket.sendto("You have been kicked",(i,OPORT))
    if temp==users:
        ##if user not found return the message to admin
        out_socket.sendto("User {0} not found".format(user),(address,OPORT))
    else :
        ##recreate the list without the user that was kicked
        users=temp

##ban user (works identical with kick, just different messages returned)     
def ban(user,address):
    global users
    temp={}
    for i in users:
        if users[i]!=user:
            temp[i]=users[i]
        else:
            out_socket.sendto("You have been banned",(i,OPORT))
    if temp==users:
        out_socket.sendto("User {0} not found".format(user),(address,OPORT))
    else :
        users=temp

        
##remove function used to remove users from the list when they quit
def remove(address):
    global users
    temp={}
    ##create a list of users without the quitting user
    ##and then reinitialise the users list
    for i in users:
        if i!=address:
            temp[i]=users[i]
    users=temp

    
##return a list of users using a special format
##used to identify the users online
def getUsers():
    userList="ulist:"
    for i in users:
        userList+=" "+users[i]
    userList+=" "
    out_socket.sendto(userList,(i,OPORT))

##send message to a certain user
##used by the private message
def sendTo(user,message,address):
    data="From "+user+": "+message
    k=0
    ##look for the recieving user
    for i in users:
        if users[i]==user:
            ##if found send message
            out_socket.sendto(data,(i,OPORT))
            k=1
    ##if user not found return message to sender
    if(k==0):
        out_socket.sendto("User {0} not found".format(user),(address,OPORT))
    

while 1:
    #step 1 - Get any data
    data,address = in_socket.recvfrom(1024)
    address=address[0] #Strip to just IP address
    ##step 2 - check for special messages
    if data=="quit":
        remove(address) #Make sure clients quit
        #break #For debugging only
    ##kick case
    elif data.startswith("/kick"):
        user=data[data.find("-")+1:]
        kick(user,address)
    ##ban case
    elif data.startswith("/ban"):
        user=data[data.find("-")+1:]
        ban(user,address)
    ##update case
    elif data.startswith("/update"):
        getUsers()
    ##private message case
    elif data.startswith("/pm"):
        user=data[data.find("-")+1:data.find(":")]
        message=data[data.find(":")+1:]
        print user,"  ",message
        sendTo(user,message,address)
    ##user case
    elif data.startswith("user"):
        #New user /change of name
        # e.g user:james
        username=data[data.find(":")+1:]
        ##change of name
        if users.has_key(address):
            sendAll("%s is now called %s"%(users[address],username))
        ##new users joining
        else:
            sendAll("%s(%s) has joined"%(username,address))                   
        users[address]=username
    ## general message 
    else:
        sendAll("%s: %s"%(users[address],data))

    
out_socket.close()
in_socket.close()
